package com.mlog.njyjy.ndop.monitor.collector.service;

import com.mlog.njyjy.ndop.monitor.collector.dao.TaskRepository;
import com.mlog.njyjy.ndop.monitor.collector.factory.ScanRouteFactory;
import com.mlog.njyjy.ndop.monitor.collector.task.AlertRunnable;
import com.mlog.njyjy.ndop.monitor.collector.task.ScanPdtRunnable;
import com.mlog.njyjy.ndop.monitor.common.domain.Task;
import com.mlog.njyjy.ndop.monitor.common.utils.CronUtil;
import com.mlog.njyjy.ndop.monitor.common.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.CamelContext;
import org.apache.camel.impl.DefaultCamelContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledFuture;

/**
 * 监控任务定时 动态添加 删除
 *
 * @author zyz
 * @version v1.0, 2020/07/28
 */
@Slf4j
@Service
public class ProductMonitorService implements ApplicationRunner {

    private final ThreadPoolTaskScheduler taskScheduler;

    private final TaskRepository taskRepository;

    private CamelContext camelContext;

    private ScanRouteFactory scanRouteFactory;

    private ConcurrentMap<String, ScheduledFuture> scheduledMap = new ConcurrentHashMap<>(1);

    @Autowired
    public ProductMonitorService(ThreadPoolTaskScheduler taskScheduler, TaskRepository taskRepository, ScanRouteFactory scanRouteFactory) {
        this.taskRepository = taskRepository;
        this.taskScheduler = taskScheduler;
        this.scanRouteFactory = scanRouteFactory;
        camelContext = new DefaultCamelContext();
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 扫描一遍 索引 tbl_pdt_monitor_task 找出哪些还没到结束时间的数据
        camelContext.start();
        List<Task> tasks = taskRepository.findLater(LocalDateTime.now());
        log.info("[monitor] will add [{}] pdt-monitor", tasks.size());
        for (Task task : tasks) {
            addTask(task);
        }
    }

    /**
     * 添加任务
     *
     * @param task
     */
    public void addTask(Task task) {
        if (task != null && LocalDateTime.now().isBefore(task.getEndProcAt())) {
            log.info("[monitor] add pdt-monitor [{}] ", task.getProductName());
            ScheduledFuture scheduledFuture;
            if (LocalDateTime.now().isBefore(task.getStartProcAt())) {
                scheduledFuture = taskScheduler.schedule(new ScanPdtRunnable(camelContext, task, taskRepository, scanRouteFactory),
                        new CronTrigger(CronUtil.formatDateByPattern(DateTimeUtil.toDate(task.getStartProcAt()))));
            } else {
                scheduledFuture = taskScheduler.schedule(new ScanPdtRunnable(camelContext, task, taskRepository, scanRouteFactory),
                        new CronTrigger(CronUtil.formatDateByPattern(DateTimeUtil.toDate(LocalDateTime.now().plusSeconds(1)))));
            }
            ScheduledFuture preOne = scheduledMap.put("monitor-" + task.getId(), scheduledFuture);
            if (preOne != null) {
                preOne.cancel(false);
            }

            ScheduledFuture alertScheduleFuture = taskScheduler.schedule(new AlertRunnable(task.getId(), taskRepository),
                    new CronTrigger(CronUtil.formatDateByPattern(DateTimeUtil.toDate(task.getAlertAt()))));
            ScheduledFuture preAlert = scheduledMap.put("alert-" + task.getId(), alertScheduleFuture);
            if (preAlert != null) {
                preAlert.cancel(false);
            }
        }

    }

    /**
     * 移除任务
     *
     * @param taskId
     */
    public void removeTask(int taskId) {
        log.info("remove task id={}", taskId);
        ScheduledFuture scheduledFuture = scheduledMap.get("monitor-" + taskId);
        if (scheduledFuture != null) {
            try {
                camelContext.stopRoute("taskId-" + taskId);
                camelContext.removeRoute("taskId-" + taskId);
                scheduledFuture.cancel(true);
                scheduledMap.remove(taskId);
                ScheduledFuture alert = scheduledMap.get("alert-" + taskId);
                alert.cancel(false);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

}
